home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / MailEnclosure / Source.v0.15 / FileShelfView.m < prev    next >
Text File  |  1995-06-12  |  8KB  |  338 lines

  1. #import "FileShelfView.h"
  2. #import "FileCollection.h"
  3. #import "TokenString.h"
  4. #import "FileName.h"
  5.  
  6. static id font;
  7.  
  8. @interface FileShelfView (PRIVATE)
  9. - _burstNames;                     
  10. - (const char *) _formatFileName: str width: (float)len; 
  11. - (NXPoint *) _pointForIndex: (int) index;
  12. - (int) _indexForPoint: (NXPoint *)hit;
  13. @end
  14.  
  15. @implementation FileShelfView
  16.  
  17. -initFrame:(const NXRect *)rect
  18. {
  19.    [super initFrame: rect];
  20.    [self registerForDraggedTypes:&NXFilenamePboardType count:1];
  21.    images = [[List alloc] init];
  22.    fileNames = [[List alloc] init];
  23.    singleNames = [[FileCollection alloc] init];
  24.    nameListDirty = NO;
  25.    font = [Font systemFontOfSize: 0 matrix: NX_IDENTITYMATRIX];
  26.  
  27.    [self setEnabled: YES];
  28.    [self setTitleWidth: 60];
  29.    [self setShowNames: YES];
  30.  
  31.    return self;
  32. }
  33.  
  34. - free
  35. {
  36.    [self unregisterDraggedTypes];
  37.    [images freeObjects];
  38.    [images free];
  39.    [fileNames freeObjects];
  40.    [fileNames free];
  41.    [singleNames freeObjects];
  42.    [singleNames free];
  43.    return [super free];
  44. }
  45.  
  46. - empty
  47. {
  48.    [images freeObjects];
  49.    [fileNames freeObjects];
  50.    [self display];
  51.    return self;
  52. }
  53.  
  54. - drawSelf:(NXRect *)r :(int) count
  55. {
  56.    NXPoint *point;
  57.    int cnt, y;
  58.    const char *label;
  59.  
  60.    /* Erase the whole view */
  61.    if(enabled)
  62.        NXDrawGrayBezel(&bounds, &bounds);    /* with bezel if enabled */
  63.    else
  64.    {
  65.       NXSetColor ([window backgroundColor]);
  66.       NXRectFill (&bounds);
  67.       return self;
  68.    }
  69.    
  70.    PSsetgray(NX_BLACK);
  71.    [font set];
  72.  
  73.    for(y = 0, cnt = [images count]; y < cnt; y++)
  74.    {
  75.       [[images objectAt: y] composite: NX_SOVER toPoint: point = [self _pointForIndex: y]];
  76.       if(showNames)
  77.       {
  78.      label = [self _formatFileName: [fileNames objectAt: y] width: titleWidth - 4.0 ]; 
  79.      PSmoveto((point->x + 24.0) - ([font getWidthOf: label]/2.0) , point->y - [font pointSize]);
  80.      PSshow(label);
  81.       }
  82.    }
  83.    return self;
  84. }
  85.  
  86. - fileNames
  87. {
  88.    if(nameListDirty)                 /* if the list has changed we need to burst it before accessing */
  89.        [self _burstNames];
  90.  
  91.    return singleNames;
  92. }
  93.  
  94. - setEnabled: (BOOL)flag             /* will it accept files? */
  95. {
  96.    if(flag == enabled)
  97.        return self;
  98.  
  99.    enabled = flag;
  100.    [self empty];
  101.    [self display];
  102.    return self;
  103. }
  104.  
  105. - (BOOL) enabled
  106. {
  107.    return enabled;
  108. }
  109.  
  110. - addFile: (const char *)filename         /* add file(s) manually */
  111. {
  112.    id file = [[StringStorage alloc] init: filename];
  113.    NXImage *image;
  114.    
  115.    image = [[Application workspace] getIconForFile: [file stringValue]];
  116.  
  117.    if(!(image && enabled))
  118.    {
  119.       [file free];
  120.       return nil;
  121.    }
  122.  
  123.    [images addObject: image];
  124.    [fileNames addObject: file];
  125.    [self display];
  126.    nameListDirty = YES;
  127.    return self;
  128. }
  129.  
  130. - mouseDown: (NXEvent *)anEvent
  131. {
  132.    NXEvent saveEvent;
  133.    NXPoint offset, origin;
  134.    Pasteboard *dragPasteboard;
  135.  
  136.    offset.x = offset.y = 0;
  137.    saveEvent = *anEvent;
  138.                          /* find the hit icon and its origin */
  139.    origin = anEvent->location;
  140.    [self convertPoint: &origin fromView: nil];
  141.    dragIndex = [self _indexForPoint: &origin];
  142.                          /* create and load pasteboard - then start drag */
  143.    dragPasteboard = [Pasteboard newName: NXDragPboard];
  144.    [dragPasteboard declareTypes: &NXFilenamePboardType num:1 owner:self];
  145.    [dragPasteboard writeType: NXFilenamePboardType data: [[fileNames objectAt: dragIndex] stringValue] 
  146.         length: [[fileNames objectAt: dragIndex] strlen]];
  147.    [self dragImage: [images objectAt: dragIndex] at: [self _pointForIndex: dragIndex] offset: &offset
  148.         event: &saveEvent pasteboard: dragPasteboard source: self slideBack: NO];
  149.  
  150.    return [super mouseDown: anEvent];
  151. }
  152.  
  153. - setShowNames: (BOOL) flag             /* Should the names appear on the shelf? */
  154. {
  155.    showNames = flag;
  156.    return self;
  157. }
  158.  
  159. -(BOOL) showNames
  160. {
  161.    return showNames;
  162. }
  163.  
  164. - setTitleWidth: (float) aWidth             /* how wide is a shelf slot - min 50 */
  165. {
  166.    titleWidth = (aWidth > 50.0 ? aWidth : 50.0);
  167.    return self;
  168. }
  169.  
  170. - (float) titleWidth
  171. {
  172.    return titleWidth;
  173. }
  174.  
  175.  
  176. @end
  177.  
  178. @implementation FileShelfView (NXDraggingDestinationProtocol)
  179. - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
  180. {
  181.  
  182.    if(enabled && ([sender draggingSourceOperationMask] & NX_DragOperationCopy))
  183.        return NX_DragOperationCopy;
  184.    else
  185.        return NX_DragOperationNone;
  186. }
  187.  
  188. - draggingExited:(id <NXDraggingInfo>) sender
  189. {
  190.    return self;
  191. }
  192.  
  193. - (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
  194. {
  195.    return YES;
  196. }
  197.  
  198. - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
  199. {
  200.    return ([self draggingEntered: sender] == NX_DragOperationNone) ? NO : YES;
  201. }
  202.  
  203. - concludeDragOperation:(id <NXDraggingInfo>)sender
  204. {
  205.    Pasteboard *pboard = [sender draggingPasteboard];
  206.    char *files;
  207.    int len;
  208.    id aFile;
  209.  
  210.    [pboard readType:NXFilenamePboardType data: &files length: &len];
  211.    if(len)
  212.    {
  213.       [images addObject: [sender draggedImageCopy]];
  214.       aFile = [[StringStorage alloc] init: files];
  215.       [fileNames addObject:aFile];
  216.       [self display];
  217.       nameListDirty = YES;
  218.    }
  219.    return self;
  220. }
  221.  
  222.  
  223. @end
  224.  
  225. @implementation FileShelfView (FSVNXDraggingSource)
  226.  
  227. - (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
  228. {
  229.    return NX_DragOperationCopy;
  230. }
  231.  
  232. - draggedImage:(NXImage *)image endedAt:(NXPoint *)screenPoint deposited:(BOOL)didDeposit
  233. {
  234.  
  235.    if(!didDeposit)
  236.    {
  237.       [[images removeObjectAt: dragIndex] free];
  238.       [[fileNames removeObjectAt: dragIndex] free];
  239.       [self display];
  240.       nameListDirty = YES;
  241.    }
  242.    return self;
  243. }
  244.  
  245. - (BOOL)ignoreModifierKeysWhileDragging
  246. {
  247.    return NO;
  248. }
  249.  
  250. @end
  251.  
  252. @implementation FileShelfView (PRIVATE)
  253. /*
  254.  * fileNames may contain multiple file entries - break them out to single entries.
  255.  */
  256. - _burstNames
  257. {
  258.    int x, cnt;
  259.    id someNames = [[TokenString alloc] init];
  260.    id aFileName;
  261.    const char *fileNameStr;
  262.    
  263.    [singleNames freeObjects];             /* free old version of the list */
  264.    [someNames setSeparator: '\t'];
  265.  
  266.    for(x = 0, cnt = [fileNames count]; x < cnt; x++)
  267.    {
  268.       [someNames setStringValue: [[fileNames objectAt: x] stringValue]];
  269.       
  270.       while(fileNameStr = [someNames popStringValue])
  271.       {
  272.      aFileName = [[StringStorage alloc] init: fileNameStr];
  273.      [singleNames addObject: aFileName];
  274.       }
  275.    }
  276.  
  277.    [someNames free];
  278.    nameListDirty = NO;
  279.    return self;
  280. }
  281.  
  282. - (const char *) _formatFileName: fn width: (float)len 
  283. {                         /* format file names like the Workspace shelf. Handle multiple items */
  284.    static char buf[MAXPATHLEN];
  285.    const char *str = [fn stringValue];
  286.    int x, cnt;
  287.  
  288.    for(cnt = 0, x = 0; str[x]; x++)
  289.    {
  290.       if(str[x] == '\t')
  291.       cnt++;
  292.    }
  293.    
  294.    if(cnt)
  295.        sprintf(buf,"%d items", cnt + 1);
  296.    else
  297.        strcpy(buf,[fn basename]);
  298.  
  299.    if([font getWidthOf: buf] > len)
  300.    {
  301.       for(x = strlen(str); x > 0 ; x--)
  302.       {
  303.      if([font getWidthOf: buf] <= len)
  304.          break;
  305.      buf[x - 1] = (char)0;
  306.       }
  307.       strcpy(buf + (x - 3), "...");
  308.    }
  309.    
  310.  
  311.    return buf;
  312. }
  313.  
  314. - (NXPoint *) _pointForIndex: (int) index    /* calculate the corner point for the nth icon */
  315. {
  316.    static NXPoint point;
  317.    int row, perRow;
  318.  
  319.    perRow = NX_WIDTH(&bounds)/titleWidth;
  320.    row = (index/perRow) + 1;
  321.    point.x = (float)((index % perRow) * titleWidth) + ((titleWidth/2.0) - 24.0);
  322.    point.y = NX_HEIGHT(&bounds) - (row * 52); 
  323.    if(showNames)
  324.        point.y -= ((row - 1) * [font pointSize]);
  325.    return &point;
  326. }
  327.  
  328. - (int) _indexForPoint: (NXPoint *)hit         /* based on a point which icon was hit? */
  329. {
  330.    int column, row;
  331.  
  332.    row = (NX_HEIGHT(&bounds) - hit->y)/(52 + (showNames ? [font pointSize] : 0));
  333.    column = hit->x/titleWidth;
  334.    return column + (row * (int)(NX_WIDTH(&bounds)/titleWidth));
  335. }
  336.  
  337. @end
  338.